package com.eastedu.report.principal.assemble;

import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.SeriesRenderData;
import com.eastedu.report.common.model.parameter.ReportGenerateParameter;
import com.eastedu.report.common.model.po.*;
import com.eastedu.report.common.util.SqlUtil;
import com.eastedu.report.mapper.*;
import com.eastedu.report.principal.model.additional.CommonRankInfo;
import com.eastedu.report.principal.model.additional.TeacherResourceUsageIndexRank;
import com.eastedu.report.principal.util.ReportTableUtil;
import com.eastedu.template.model.ChartData;
import com.eastedu.template.model.SeriesData;
import com.eastedu.template.util.ChartDataUtil;
import com.google.common.collect.Maps;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 附件数据组装
 *
 * @author superman
 */
@Service
public class AdditionalReportDataAssembly implements ReportDataAssembly {

    private final TeacherResourceUsageIndexMapper teacherResourceUsageIndexMapper;
    private final TeacherTeachingActivityPrepareResourceUsageDetailMapper prepareResourceUsageDetailMapper;
    private final TeacherTeachingActivityTeachingResourceUsageDetailMapper teachingResourceUsageDetailMapper;
    private final TeacherTeachingActivityResearchResourceUsageDetailMapper researchResourceUsageDetailMapper;
    private final TeacherTeachingActivityStudentResourceUsageDetailMapper studentActivityResourceUsageDetailMapper;
    private final TeacherTeachingActivityExamResourceUsageDetailMapper examResourceUsageDetailMapper;
    private final TeacherTeachingActivityResourceUsageRateMapper teacherTeachingActivityResourceUsageRateMapper;

    /**
     * Instantiates a new Additional report data assembly.
     *
     * @param teacherResourceUsageIndexMapper                the teacher resource usage index mapper
     * @param prepareResourceUsageDetailMapper               the prepare resource usage detail mapper
     * @param teachingResourceUsageDetailMapper              the teaching resource usage detail mapper
     * @param researchResourceUsageDetailMapper              the research resource usage detail mapper
     * @param studentActivityResourceUsageDetailMapper       the student activity resource usage detail mapper
     * @param examResourceUsageDetailMapper                  the exam resource usage detail mapper
     * @param teacherTeachingActivityResourceUsageRateMapper the teacher resource usage rate mapper
     */
    public AdditionalReportDataAssembly(TeacherResourceUsageIndexMapper teacherResourceUsageIndexMapper,
                                        TeacherTeachingActivityPrepareResourceUsageDetailMapper prepareResourceUsageDetailMapper, TeacherTeachingActivityTeachingResourceUsageDetailMapper teachingResourceUsageDetailMapper, TeacherTeachingActivityResearchResourceUsageDetailMapper researchResourceUsageDetailMapper, TeacherTeachingActivityStudentResourceUsageDetailMapper studentActivityResourceUsageDetailMapper, TeacherTeachingActivityExamResourceUsageDetailMapper examResourceUsageDetailMapper,
                                        TeacherTeachingActivityResourceUsageRateMapper teacherTeachingActivityResourceUsageRateMapper) {
        this.teacherResourceUsageIndexMapper = teacherResourceUsageIndexMapper;
        this.prepareResourceUsageDetailMapper = prepareResourceUsageDetailMapper;
        this.teachingResourceUsageDetailMapper = teachingResourceUsageDetailMapper;
        this.researchResourceUsageDetailMapper = researchResourceUsageDetailMapper;
        this.studentActivityResourceUsageDetailMapper = studentActivityResourceUsageDetailMapper;
        this.examResourceUsageDetailMapper = examResourceUsageDetailMapper;
        this.teacherTeachingActivityResourceUsageRateMapper = teacherTeachingActivityResourceUsageRateMapper;
    }

    @Override
    public Map<String, Object> assemble(ReportGenerateParameter parameter, List<String> schoolPeriods, List<String> subjects) {
        Map<String, Object> reportData = Maps.newHashMap();

        List<TeacherResourceUsageIndexRank> teacherResourceUsageIndexRanks = SqlUtil.query(parameter,
                                                                                           teacherResourceUsageIndexMapper,
                                                                                           TeacherResourceUsageIndexPO.class,
                                                                                           ReportTableUtil::getTeacherResourceUsageIndexRank);

        List<TeacherResourceUsageIndexRank> ranks = teacherResourceUsageIndexRanks.stream()
                .filter(s -> StringUtils.isNotBlank(s.getIndex()) && !"-".equals(s.getIndex()) && Objects.nonNull(s.getRank()))
                .filter(s -> (s.getRank() <= 10 && Double.parseDouble(s.getIndex()) > 0D))
                .sorted(Comparator.comparing(ReportTableUtil.comparing()))
                .collect(Collectors.toList());
        // 一、整体概述: 本月"教师资源应用指数"排名
        reportData.put("teacher_resource_usage_index_rank_desc", TopDescription.getDescription(ranks));
        // 教师资源应用指数排名图表
        reportData.put("teacher_resource_usage_index_rank_chart_show", !ranks.isEmpty());
        reportData.put("teacher_resource_usage_index_rank_chart", getTeacherResourceUsageIndexChart(ranks));


        // 附件一：本月教师资源应用指数排名
        reportData.put("teacher_resource_usage_index_rank_table", teacherResourceUsageIndexRanks);

        // 附件二：本月教师同步备课环节资源使用个数排名
        reportData.put("teacher_prepare_lesson_usage_rank_table", SqlUtil.query(parameter,
                                                                                prepareResourceUsageDetailMapper,
                                                                                TeacherTeachingActivityPrepareResourceUsageDetailPO.class,
                                                                                ReportTableUtil::getTeacherPrepareLessonUsageRank));
        // 附件三：本月教师同步教学环节资源使用个数排名
        reportData.put("teacher_teaching_usage_rank_table", SqlUtil.query(parameter,
                                                                          teachingResourceUsageDetailMapper,
                                                                          TeacherTeachingActivityTeachingResourceUsageDetailPO.class,
                                                                          ReportTableUtil::getTeacherTeachingUsageRank));
        // 附件四：本月教师同步教研环节资源使用个数排名
        reportData.put("teacher_research_usage_rank_table", SqlUtil.query(parameter,
                                                                          researchResourceUsageDetailMapper,
                                                                          TeacherTeachingActivityResearchResourceUsageDetailPO.class,
                                                                          ReportTableUtil::getTeacherResearchUsageRank));
        // 附件五：本月教师学生活动环节资源使用个数排名
        reportData.put("teacher_student_activity_usage_rank_table", SqlUtil.query(parameter,
                                                                                  studentActivityResourceUsageDetailMapper,
                                                                                  TeacherTeachingActivityStudentResourceUsageDetailPO.class,
                                                                                  ReportTableUtil::getTeacherStudentActivityUsageRank));
        // 附件六：本月教师同步测验环节资源使用个数排名
        reportData.put("teacher_exam_usage_rank_table", SqlUtil.query(parameter,
                                                                      examResourceUsageDetailMapper,
                                                                      TeacherTeachingActivityExamResourceUsageDetailPO.class,
                                                                      ReportTableUtil::getTeacherExamUsageRank));

        // 附件七：截止本月，本学期教师同步资源使用率排名
        reportData.put("teacher_resource_usage_rate_rank_table", SqlUtil.query(parameter,
                                                                               teacherTeachingActivityResourceUsageRateMapper,
                                                                               TeacherTeachingActivityResourceUsageRatePO.class,
                                                                               ReportTableUtil::getTeacherResourceUsageRateRank));
        return reportData;
    }

    private static ChartMultiSeriesRenderData getTeacherResourceUsageIndexChart(List<TeacherResourceUsageIndexRank> ranks) {
        return ChartDataUtil.convertChartData(new ChartData("本月\"教师资源应用指数\"排名",
                                                            ranks.stream()
                                                                    .sorted(Comparator.comparing(ReportTableUtil.comparing()))
                                                                    .map(CommonRankInfo::getTeacherName)
                                                                    .toArray(String[]::new),
                                                            Collections.singletonList(new SeriesData("教师资源应用指数", 0,
                                                                                                     ranks.stream()
                                                                                                             .sorted(Comparator.comparing(ReportTableUtil.comparing()))
                                                                                                             .map(TeacherResourceUsageIndexRank::getIndex)
                                                                                                             .map(Double::valueOf)
                                                                                                             .toArray(Number[]::new),
                                                                                                     SeriesRenderData.ComboType.BAR))));
    }


    /**
     * The enum Top description.
     */
    @Getter
    enum TopDescription {
        /**
         * None top description.
         */
        NONE((size) -> size <= 0, 0, "本月，本学校教师的“教师资源应用指数”均为0。"),
        /**
         * Top 1 top description.
         */
        TOP1((size) -> size > 0 && size <= 3, 1, "{0}获得本月“教师资源应用指数”第一名。"),
        /**
         * Top 3 top description.
         */
        TOP3((size) -> size > 3, 3, "{0}获得本月“教师资源应用指数”前三名。"),
        ;
        private final Predicate<Integer> predicate;
        private final int limit;
        private final String description;

        TopDescription(Predicate<Integer> predicate, int limit, String description) {
            this.predicate = predicate;
            this.limit = limit;
            this.description = description;
        }

        /**
         * Gets description.
         *
         * @param ranks the ranks
         * @return the description
         */
        public static String getDescription(List<TeacherResourceUsageIndexRank> ranks) {
            for (TopDescription value : values()) {
                if (value.predicate.test(ranks.size())) {
                    return MessageFormat.format(value.getDescription(), ranks.stream()
                            .filter(s -> s.getRank() <= value.limit)
                            .sorted(Comparator.comparing(ReportTableUtil.comparing()))
                            .map(CommonRankInfo::getTeacherName)
                            .collect(Collectors.joining("、")));
                }
            }
            return null;
        }
    }
}
